#include <iostream>
#include <unistd.h>
#include <string>
#include <pthread.h>

using namespace std;

// pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//也可定义全局条件变量使用
// pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

#define NUM 4
typedef void (*func_t)(const string &name, pthread_mutex_t *mtx, pthread_cond_t *cond);
volatile bool quit = false;

class ThreadData
{
public:
    ThreadData(const string &name, pthread_mutex_t *mtx, pthread_cond_t *cond, func_t func_)
        : name_(name), cond_(cond), mtx_(mtx), func_(func_)
    {
    }

public:
    func_t func_;
    string name_;
    pthread_mutex_t *mtx_;
    pthread_cond_t *cond_;
};

void fun1(const string &name, pthread_mutex_t *mtx, pthread_cond_t *cond)
{
    while (!quit)
    {
         // wait一定要在加锁和解锁之间进行wait！---要访问临界资源
        pthread_mutex_lock(mtx);
        pthread_cond_wait(cond, mtx); //默认该线程在执行的时候，wait代码被执行，当前线程会被立即被阻塞
        cout << "运输..." << endl;
        pthread_mutex_unlock(mtx);
    }
}
void fun2(const string &name, pthread_mutex_t *mtx, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mtx);
        pthread_cond_wait(cond, mtx);
         if (!quit)
         cout << "加载..." << endl;
        pthread_mutex_unlock(mtx);
    }
}
void fun3(const string &name, pthread_mutex_t *mtx, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mtx);
        pthread_cond_wait(cond, mtx);
        cout << "分析..." << endl;
        pthread_mutex_unlock(mtx);
    }
}
void fun4(const string &name, pthread_mutex_t *mtx, pthread_cond_t *cond)
{
    while (!quit)
    {
        pthread_mutex_lock(mtx);
        pthread_cond_wait(cond, mtx);
        cout << "传输..." << endl;
        pthread_mutex_unlock(mtx);
    }
}

void *Entry(void *args)
{
    ThreadData *td = (ThreadData *)args;//td在每一个线程自己私有的栈空间中保存
    td->func_(td->name_, td->mtx_, td->cond_);// 它是一个函数，调用完成就要返回！
    delete td;//别忘记析构，防止内存泄漏
    return nullptr;
}

int main()
{
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx, nullptr);
    pthread_cond_init(&cond, nullptr);

    func_t func[NUM] = {fun1, fun2, fun3, fun4};
    pthread_t tids[NUM];
    for (int i = 0; i < NUM; i++)
    {
        string name = "thread ";
        name += to_string(i + 1);
        ThreadData *td = new ThreadData(name, &mtx, &cond, func[i]);
        pthread_create(tids + i, nullptr, Entry, (void *)td);
    }

    sleep(4);

    int count = 8;
    while (count--)
    {
        cout << "resume thread run code ...." << endl;
        // pthread_cond_signal(&cond);// 将线程从等待队列唤醒
        pthread_cond_broadcast(&cond);
        sleep(1);
    }

    cout << "------" << endl;
    quit = true;
    pthread_cond_broadcast(&cond); // 将线程从等待队列唤醒

    for (int i = 0; i < NUM; i++)
    {
        pthread_join(tids[i], nullptr);
        cout << "thread: " << tids[i] << "quit" << endl;
    }

    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);

    return 0;
}
